<template>
  <Row :gutter="15">
    <Col :span="9">
      <database titleLabel="源" :igSqlite="true" :dbIndex="source.dbIndex" :schema="source.schema" @change="onSourceSchemaChanged" />
    </Col>
    <Col :span="9">
      <database titleLabel="目标" :igSqlite="true" :dbIndex="target.dbIndex" :schema="target.schema" @change="onTargetSchemaChanged" />
    </Col>
    <Col :span="6" class="btn-group" style="text-align: right">
      <Button type="primary" @click="onBeginCompare"><DiffFilled /> 开始比较</Button>
      <Button type="default" @click="onBuildScripts" :disabled="!canBuildScript"><ThunderboltFilled /> 生成脚本</Button>
    </Col>
  </Row>
  <Row :gutter="10" v-show="comparedResults.source">
    <Col :span="7">
      <Card size="small" title="需要添加的表" :bodyStyle="getBodyStyle(detailHeight / 3)">
        <template #extra>
          <Switch v-model:checked="selectAllAdds" style="margin-right: 10px">
            <template #checkedChildren>全部</template>
            <template #unCheckedChildren>取消</template>
          </Switch>
          <Badge :count="(comparedResults.adds || []).length" :show-zero="true" />
        </template>
        <p v-for="item of comparedResults.adds">
          <Switch v-model:checked="item.Checked" />
          <Tooltip placement="topLeft" :title="displayTable(item)">
            {{ item.name }} <i v-if="item.comment">({{ item.comment }})</i>
          </Tooltip>
        </p>
        <template v-if="(comparedResults.adds || []).length == 0">
          <p>无</p>
        </template>
      </Card>
      <Card size="small" style="margin-top: 5px" title="需要修改的表" :bodyStyle="getBodyStyle(detailHeight / 3 + 26)">
        <template #extra>
          <Switch v-model:checked="selectAllChangeds" style="margin-right: 10px">
            <template #checkedChildren>全部</template>
            <template #unCheckedChildren>取消</template>
          </Switch>
          <Badge :count="(comparedResults.changeds || []).length" :show-zero="true" />
        </template>
        <p v-for="item of comparedResults.changeds">
          <Switch v-model:checked="item.Checked" />
          <Tooltip placement="topLeft" :title="displayTable(item)">
            {{ item.table }} <i v-if="item.comment">({{ item.comment }})</i>
          </Tooltip>
        </p>
        <template v-if="(comparedResults.changeds || []).length == 0">
          <p>无</p>
        </template>
      </Card>
      <Card size="small" style="margin-top: 5px" title="可以删除的表" :bodyStyle="getBodyStyle(detailHeight / 3 - 30)">
        <template #extra>
          <Switch v-model:checked="selectAllRemoves" style="margin-right: 10px">
            <template #checkedChildren>全部</template>
            <template #unCheckedChildren>取消</template>
          </Switch>
          <Badge :count="(comparedResults.removes || []).length" :show-zero="true" />
        </template>
        <p v-for="item of comparedResults.removes">
          <Switch v-model:checked="item.Checked" />
          <Tooltip placement="topLeft" :title="displayTable(item)">
            {{ item.name }} <i v-if="item.comment">({{ item.comment }})</i>
          </Tooltip>
        </p>
      </Card>
    </Col>
    <Col :span="17">
      <Card size="small" title="生成的脚本" class="sql-script" :bodyStyle="getBodyStyle(detailHeight + 82, '#f6f6f6')">
        <template #extra>
          <Button type="primary" shape="round" :disabled="!scripts.length" @click="onCopyScript"><CopyFilled /> 复制脚本</Button>
        </template>
        <pre id="scripts"><template v-for="item of scripts">{{item}}<br v-if="item" /></template></pre>
      </Card>
    </Col>
  </Row>
</template>

<script setup>
  import { useStore } from 'vuex';
  import { ref, reactive, watch, inject, onMounted } from 'vue';
  import { Card, Row, Col, Switch, Tooltip, Badge, Button } from 'ant-design-vue';
  import { DiffFilled, ThunderboltFilled, CopyFilled } from '@ant-design/icons-vue';

  import database from './components/Database.vue';

  const $store = useStore();
  const $http = inject('$http');
  const $eventBus = inject('$eventBus');
  const $message = inject('$message');
  const $copyText = inject('$copyText');

  const detailHeight = ref(420);
  const canBuildScript = ref(false);
  const selectAllAdds = ref(true);
  const selectAllChangeds = ref(true);
  const selectAllRemoves = ref(false);
  const scripts = ref([]);

  const source = reactive({ dbIndex: '0', schema: '' });
  const target = reactive({ dbIndex: '0', schema: '' });
  const comparedResults = reactive({
    source: null,
    target: null,
    adds: [],
    changeds: [],
    removes: []
  });

  watch(selectAllAdds, n => (comparedResults.adds || []).forEach(item => (item.Checked = n)));
  watch(selectAllChangeds, n => (comparedResults.changeds || []).forEach(item => (item.Checked = n)));
  watch(selectAllRemoves, n => (comparedResults.removes || []).forEach(item => (item.Checked = n)));

  function getBodyStyle(height, color) {
    return {
      'overflow': 'auto',
      'max-height': height + 'px',
      'min-height': height + 'px',
      'background': color || 'transparent'
    };
  }

  function displayTable(item) {
    if (item.comment) {
      return `${item.name || item.table}(${item.comment})`;
    }

    return item.name;
  }

  function onSourceSchemaChanged(data) {
    source.type = data.type;
    source.schema = data.schema;
    source.dbIndex = data.dbIndex;
  }

  function onTargetSchemaChanged(data) {
    target.type = data.type;
    target.schema = data.schema;
    target.dbIndex = data.dbIndex;
  }

  function onBeginCompare() {
    if (source.dbIndex == target.dbIndex && source.schema == target.schema) {
      $message.warning('源数据库和目标数据库相同，请选择不同的数据库再作比较！');

      return;
    }

    if (source.type != target.type) {
      $message.warning(`源数据库(${source.type})和目标数据库类型(${target.type})不同，暂不支持不同类型的数据库比较！`);

      return;
    }

    scripts.value = [];
    selectAllAdds.value = true;
    selectAllChangeds.value = true;
    selectAllRemoves.value = false;
    canBuildScript.value = false;

    $http.get(`/api/db/compare/${source.dbIndex}/${source.schema}/to/${target.dbIndex}/${target.schema}`, { spinText: '正在比较中，请稍后...' }).then(res => {
      comparedResults.source = res.source;
      comparedResults.target = res.target;
      comparedResults.adds = res.adds;
      comparedResults.changeds = res.changeds;
      comparedResults.removes = res.removes;

      canBuildScript.value = true;

      (comparedResults.adds || []).forEach(item => (item.Checked = true));
      (comparedResults.changeds || []).forEach(item => (item.Checked = true));
      (comparedResults.removes || []).forEach(item => (item.Checked = false));
    });
  }

  function onBuildScripts() {
    if (comparedResults.source) {
      let submitDatas = {
        source: comparedResults.source,
        target: comparedResults.target,
        adds: (comparedResults.adds || []).filter(item => item.Checked),
        changeds: (comparedResults.changeds || []).filter(item => item.Checked),
        removes: (comparedResults.removes || []).filter(item => item.Checked)
      };

      $http.post('/api/db/compare/ddl/build', submitDatas, { spinText: '脚本生成中，请稍后...' }).then(res => {
        scripts.value = res;
      });
    }
  }

  function onCopyScript() {
    $copyText(document.getElementById('scripts').innerText).then(() => {
      $message.success('脚本已复制！');
    });
  }

  function ResizeDetailPanel(area) {
    detailHeight.value = area.height - 215;
  }

  onMounted(() => {
    let area = $store.state.area.content;

    ResizeDetailPanel(area);

    $eventBus.on('windowResizeChanged', client => ResizeDetailPanel(client));
  });
</script>

<style lang="less" scoped>
  .ant-tooltip {
    max-width: 100%;
    border-radius: 5px;
  }

  .ant-card-head {
    .ant-switch {
      top: 0;
    }
  }

  .ant-card-body {
    p {
      font-size: 14px;
      font-weight: normal;
      padding: 6px 0 6px 0;
      white-space: nowrap;
      text-overflow: clip;
      overflow: hidden;
      margin-bottom: 0;
      line-height: 1;
      vertical-align: middle;
      cursor: default;
      border-bottom: 1px dashed #e0e0e0;

      >.ant-switch{
        margin-right: 5px;
      }

      > i {
        font-weight: normal;
      }

      > span {
        cursor: default;
        display: inline-block;
        padding-left: 5px;
        user-select: all;
      }
    }

    p:last-of-type {
      border-bottom: 1px solid transparent;
    }
  }

  .sql-script {
    .ant-card-body {
      pre {
        font-size: 12px;
        margin-bottom: 0;
        overflow: hidden;
        cursor: default;
      }
    }
  }
</style>
